﻿using HelixToolkit.Wpf;
using LxCFD;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace TimeSolve
{
    public class GraphDataBase
    {
        public GraphDataBase(FvMesh mesh)
        {
            calBoundary(mesh);
            CreatGeometry cg = new CreatGeometry();
            arrow = cg.createArrow();
        }
        public GraphBound graphBound { get; set; }
        public Model3DGroup arrow { get; set; }
        public class GraphBound
        {
            public double minX { get; set; }
            public double minY { get; set; }
            public double minZ { get; set; }
            public double maxX { get; set; }
            public double maxY { get; set; }
            public double maxZ { get; set; }
            public Point3D center { get; set; }
            public double radiusBound { get; set; }
            public void calCenter()
            {
                center = new Point3D((minX + maxX) / 2, (minY + maxY) / 2, (minZ + maxZ) / 2);
                Vector3D v = new Point3D(maxX, maxY, maxZ) - center;
                radiusBound = v.Length;
            }
        }
        private void calBoundary(FvMesh mesh)
        {
            graphBound = new GraphBound();
            foreach(FvZone z in mesh.Zones)
            {
                foreach (Point3D p in z.Nodes)
                {
                    if (p.X < graphBound.minX)
                    {
                        graphBound.minX = p.X;
                    }
                    else if (p.X > graphBound.maxX)
                    {
                        graphBound.maxX = p.X;
                    }
                    if (p.Y < graphBound.minY)
                    {
                        graphBound.minY = p.Y;
                    }
                    else if (p.Y > graphBound.maxY)
                    {
                        graphBound.maxY = p.Y;
                    }
                    if (p.Z < graphBound.minZ)
                    {
                        graphBound.minZ = p.Z;
                    }
                    else if (p.Z > graphBound.maxZ)
                    {
                        graphBound.maxZ = p.Z;
                    }
                }
            }

            graphBound.calCenter();
        }
        public static Brush getBrush(int n)
        {
            int i = n % 5;
            BrushConverter brushConverter = new BrushConverter();

            switch (i)
            {
                case 0:
                    return (Brush)brushConverter.ConvertFromString("#0099CC");
                case 1:
                    return (Brush)brushConverter.ConvertFromString("#FF9933");
                case 2:
                    return (Brush)brushConverter.ConvertFromString("#009966");
                case 3:
                    return (Brush)brushConverter.ConvertFromString("#993333");
                case 4:
                    return (Brush)brushConverter.ConvertFromString("#336633");
                default:
                    return (Brush)brushConverter.ConvertFromString("#3366CC");
            }
        }
        public static Material getMetalMaterial(Brush brush, byte specularBrightness, byte ambient)
        {
            var mg = new MaterialGroup();
            mg.Children.Add(new DiffuseMaterial(brush) { AmbientColor = Color.FromRgb(ambient, ambient, ambient) });
            //ambientColor应该表示环境光及其强度。a color that represents how the material reflects AmbientLight.
            //第三个属性color，是纹理的筛选器。

            mg.Children.Add(new SpecularMaterial(new SolidColorBrush(Color.FromRgb(specularBrightness, specularBrightness, specularBrightness)), 100));
            //specularPower是反光度（specularPower现数值100的），值的区间没说明。
            //第三个属性color（This property has the effect of filtering the material applied to the model by the color value specified. For example, setting this property to Colors.Red would occlude blue and green in the material.
            return mg;
        }
        public static LinearGradientBrush getSteppedGradientBrush(IList<Color> colors)
        {
            var brush = new LinearGradientBrush { StartPoint = new Point(0, 0), EndPoint = new Point(0, 1) };
            int n = colors.Count;
            for (int i = 0; i < n; i++)
            {
                var gs0 = new GradientStop(colors[i], (double)i / n);
                var gs1 = new GradientStop(colors[i], (double)(i + 1) / n);
                brush.GradientStops.Add(gs0);
                brush.GradientStops.Add(gs1);
            }
            return brush;
        }
        public static LinearGradientBrush getSteppedGradientBrushDefault()
        {
            var brush = new LinearGradientBrush { StartPoint = new Point(0, 0), EndPoint = new Point(0, 1) };
            string[] colors = StringColros;
            int n = colors.Length;
            for (int i = 0; i < n; i++)
            {
                var gs0 = new GradientStop((Color)ColorConverter.ConvertFromString(colors[i]), (double)i / n);
                var gs1 = new GradientStop((Color)ColorConverter.ConvertFromString(colors[i]), (double)(i + 1) / n);
                brush.GradientStops.Add(gs0);
                brush.GradientStops.Add(gs1);
            }
            return brush;
        }

        public static Brush[] getBrushList()
        {
            return stringsToBrushes(StringColros);
        }
        private static Brush[] stringsToBrushes(string[] colorsInStringFormat)
        {
            BrushConverter bc = new BrushConverter();
            Brush[] brushes = new Brush[colorsInStringFormat.Length];
            for (int i = 0; i < brushes.Length; i++)
            {
                brushes[i] = (Brush)bc.ConvertFromString(colorsInStringFormat[brushes.Length - i - 1]);
            }
            return brushes;
        }
        public static string[] StringColros { get; set; } = new string[] { "#FE0115" , "#FE7E00" , "#FDBE00" , "#FFFF01" , "#C9FE00" , "#36FD00" , "#38FD00" , "#00E1CF" , "#0182DE" , "#020DFF" };

    }
}


//this.faceTris= new Dictionary<string, Int32Collection>();
//foreach (Mesh.Zone z in mesh.zones)
//{
//    foreach (Mesh.Thread t in z.threads)
//    {
//        if (!faceTris.ContainsKey(t.name + "0"))
//        {
//            Int32Collection ic0 = new Int32Collection();
//            Int32Collection ic1 = new Int32Collection();
//            for (int iii = 0; iii < t.faces.Length; iii++)
//            {
//                for (int ii2 = 2; ii2 < t.faces[iii].facenodes.Length; ii2++)
//                {
//                    ic0.Add(t.faces[iii].facenodes[0]);
//                    ic0.Add(t.faces[iii].facenodes[ii2 - 1]);
//                    ic0.Add(t.faces[iii].facenodes[ii2]);

//                    ic1.Add(t.faces[iii].facenodes[0]);
//                    ic1.Add(t.faces[iii].facenodes[ii2]);
//                    ic1.Add(t.faces[iii].facenodes[ii2 - 1]);
//                }
//            }
//            faceTris.Add(t.name + "0", ic0);
//            faceTris.Add(t.name + "1", ic1);
//        }

//    }
//}
//public void buildMeshWithWire(out GeometryModel3D geometryModel3D,out LinesVisual3D linesVisual3D,Mesh.Face[] faces, int startIndex, int endIndex, Brush brush)
//{
//    LinesVisual3D li = new LinesVisual3D();
//    li.Color = Colors.Black;
//    li.Thickness = 1;


//    MeshGeometry3D meshGeometry3D = new MeshGeometry3D();

//    meshGeometry3D.Positions = this.point3Ds;

//    Int32Collection TriangleIndices = new Int32Collection();
//    for (int ii = startIndex; ii <= endIndex; ii++)
//    {
//        for (int i2 = 2; i2 < faces[ii].facenodes.Length; i2++)
//        {
//            TriangleIndices.Add(faces[ii].facenodes[0]);
//            TriangleIndices.Add(faces[ii].facenodes[i2 - 1]);
//            TriangleIndices.Add(faces[ii].facenodes[i2]);

//            TriangleIndices.Add(faces[ii].facenodes[0]);
//            TriangleIndices.Add(faces[ii].facenodes[i2]);
//            TriangleIndices.Add(faces[ii].facenodes[i2 - 1]);

//        }
//        for (int i2 = 0; i2 < faces[ii].facenodes.Length-1; i2++)
//        {
//            li.Points.Add(point3Ds[faces[ii].facenodes[i2]]);
//            li.Points.Add(point3Ds[faces[ii].facenodes[i2+1]]);
//        }
//        li.Points.Add(point3Ds[faces[ii].facenodes[faces[ii].facenodes.Length - 1]]);
//        li.Points.Add(point3Ds[faces[ii].facenodes[0]]);

//    }
//    meshGeometry3D.TriangleIndices = TriangleIndices;

//    geometryModel3D = new GeometryModel3D() { Geometry = meshGeometry3D, Material = MeshRenderLib.getMetalMaterial(brush, 255, 255) };

//    linesVisual3D = li;
//}

//public LinesVisual3D buildMeshWire()
//{
//    LinesVisual3D linesVisual3D = new LinesVisual3D();
//    linesVisual3D.Color = Colors.White;
//    linesVisual3D.Thickness = 1;
//    Point3DCollection ps = new Point3DCollection();
//    for(int i = 0; i < point3Ds.Count - 1; i++)
//    {
//        ps.Add(point3Ds[i]);
//        ps.Add(point3Ds[i + 1]);
//    }
//    linesVisual3D.Points = ps;
//    return linesVisual3D;
//}




// public double bound { get;private  set; }//图像边界
//public void buildmesh(out GeometryModel3D side1,out GeometryModel3D side2,Mesh.Face[] faces,int startIndex,int endIndex,Brush brush)
//{
//    if (this.point3Ds.Count == 0)
//    {
//        side1 = null;
//        side2 = null;
//        return;
//    }

//    MeshGeometry3D meshGeometry3D_1 = new MeshGeometry3D();
//    MeshGeometry3D meshGeometry3D_2 = new MeshGeometry3D();
//    meshGeometry3D_1.Positions = this.point3Ds;
//    meshGeometry3D_2.Positions = this.point3Ds;
//    Int32Collection TriangleIndices_1 = new Int32Collection();
//    Int32Collection TriangleIndices_2 = new Int32Collection();
//    for (int ii = startIndex; ii <= endIndex; ii++)
//    {
//        for (int i2 = 2; i2 < faces[ii].facenodes.Length; i2++)
//        {
//            TriangleIndices_1.Add(faces[ii].facenodes[0]);
//            TriangleIndices_1.Add(faces[ii].facenodes[i2 - 1]);
//            TriangleIndices_1.Add(faces[ii].facenodes[i2]);

//            TriangleIndices_2.Add(faces[ii].facenodes[0]);
//            TriangleIndices_2.Add(faces[ii].facenodes[i2]);
//            TriangleIndices_2.Add(faces[ii].facenodes[i2 - 1]);
//        }
//    }
//    meshGeometry3D_1.TriangleIndices = TriangleIndices_1;
//    meshGeometry3D_2.TriangleIndices = TriangleIndices_2;
//    Material material = getMetalMaterial(brush, 125, 125);
//    side1 = new GeometryModel3D() { Geometry = meshGeometry3D_1, Material = material };
//    side2 = new GeometryModel3D() { Geometry = meshGeometry3D_2, Material = material };
//}
//public static void  buildHelixWire(Point3DCollection ps,Mesh.Face[] faces, int startIndex, int endIndex)
//{
//    //Point3DCollection ps = new Point3DCollection();
//    for (int ii = startIndex; ii <= endIndex; ii++)
//    {
//        ps.Add(MainViewModel.mainViewModel.mesh.nodes[faces[ii].facenodes[faces[ii].facenodes.Length - 1]]);
//        foreach (int ii3 in faces[ii].facenodes)
//        {
//            ps.Add(MainViewModel.mainViewModel.mesh.nodes[ii3]);
//            ps.Add(MainViewModel.mainViewModel.mesh.nodes[ii3]);
//        }
//        ps.RemoveAt(ps.Count - 1);
//    }
//}
//public void  buildMeshWire(Mesh.Face[] faces, int startIndex, int endIndex,Material material,GraphData graphViewport)
//{
//    Int32Collection ic = new Int32Collection();
//    for (int ii = startIndex; ii <= endIndex; ii++)
//    {
//        for (int i2 = 0; i2 < faces[ii].facenodes.Length - 1; i2++)
//        {
//            //查重
//            if(isValidLine (ic, faces[ii].facenodes[i2], faces[ii].facenodes[i2 + 1]))
//            {
//                ic.Add(faces[ii].facenodes[i2]);
//                ic.Add(faces[ii].facenodes[i2+1]);

//            }   
//        }
//        if (isValidLine(ic, faces[ii].facenodes[0], faces[ii].facenodes[faces[ii].facenodes.Length - 1]))
//        {
//            ic.Add(faces[ii].facenodes[0]);
//            ic.Add(faces[ii].facenodes[faces[ii].facenodes .Length -1]);
//        }

//    }

//    for(int i3 = 0; i3 < ic.Count-1; i3 += 2)
//    {
//        GeometryModel3D geo = new GeometryModel3D();
//        geo.Geometry = lineBase;
//        geo.Material = material;

//        Transform3DGroup transform3DGroup = new Transform3DGroup();
//        transform3DGroup.Children.Add(graphViewport.lineWidthScale);
//        Matrix3D matrix3D;
//        Point3D p1 = this.point3Ds[ic[i3]];
//        Vector3D v12 = this.point3Ds[ic[i3 + 1]] - p1;
//        Vector3D v = v12 / v12.Length;
//        double x2 = v.X * v.X;
//        double y2 = v.Y * v.Y;
//        double x2y2 = x2 + y2;
//        if (x2y2 == 0)
//        {
//            if (Vector3D.DotProduct(new Vector3D(0, 0, 1), v12)>=0)
//            {
//                matrix3D = new Matrix3D();
//            }else
//            {
//                matrix3D = new Matrix3D(
//                    1, 0, 0, 0,
//                    0, -1, 0, 0,
//                    0, 0, -1, 0,
//                    0, 0, 0, 1);
//            }

//        }else
//        {
//            double x2d = x2 / x2y2;
//            double y2d = y2 / x2y2;
//            double xyd = v.X * v.Y / x2y2;
//            matrix3D= new Matrix3D(
//                y2d + x2d * v.Z, -xyd * (1 - v.Z), -v.X, 0,
//                -xyd * (1 - v.Z), x2d + y2d * v.Z, -v.Y, 0,
//                v.X, v.Y, v.Z, 0,
//                0, 0, 0, 1);
//        }

//        matrix3D.ScalePrepend(new Vector3D(1, 1, v12.Length));
//        matrix3D.Translate((Vector3D)p1);

//        MatrixTransform3D matrixTransform3D = new MatrixTransform3D(matrix3D);
//        matrixTransform3D.Freeze();
//        transform3DGroup.Children.Add(matrixTransform3D);
//        geo.Transform = transform3DGroup;
//        graphViewport.lines.Children.Add(geo);
//    }
//    //return model3DGroup;
//}
//public void buildMeshWireVisual(Int32Collection nodes,MeshGeometry3D geo,Vector3D lookDir,Vector3D voff,double xiankuanxishu)
//{

//    for (int i2 = 0; i2 < nodes.Count  - 1; i2 += 2)
//    {
//        Vector3D v = point3Ds[i2 + 1] - point3Ds[i2];
//        Vector3D v2 = VectorCal.Cross(lookDir, v);

//        Vector3D v3 = xiankuanxishu / v2.Length * v2;
//        mg.Positions.Add(ps[iii] + voff + v3);
//        mg.Positions.Add(ps[iii] + voff - v3);
//        mg.Positions.Add(ps[iii + 1] + voff + v3);
//        mg.Positions.Add(ps[iii + 1] + voff - v3);
//        geo.Positions[i2*2]
//    }
//}
//public static bool isValidLine(Int32Collection ic,int a,int b)
//{
//    return true;
//    for (int i3 = 0; i3 < ic.Count -1; i3 += 2)
//    {
//        if (ic[i3]==a&&ic[i3+1]==b)//包含
//        {
//            return false;
//        }else if (ic[i3] == b && ic[i3 + 1] == a)
//        {
//            return false;
//        }
//    }
//    return true;
//}